/**
 * Copyright 2008 Benjamin Possolo
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.javenue.util.process;

import org.javenue.util.process.impl.TransitionManagerImpl;

/**
 * A <tt>TransitionManager</tt> is responsible for executing <tt>Transition</tt> or <tt>TransitionWithResult</tt> instances
 * on behalf of a <tt>Process</tt>.
 * <p>
 * The <tt>TransitionManager</tt> ensures that transitions are executed in an atomic/transactional fashion and that
 * the <tt>ProcessState</tt> object of a given <tt>Process</tt> is automatically loaded from the persistence store
 * before a transition is executed and then persisted back to the persistence
 * store after the transition completes successfully.
 * 
 * @see TransitionManagerImpl
 * @author Benjamin Possolo
 * <p>Created on Jun 28, 2008
 */
public interface TransitionManager {
	
	/**
	 * Executes a <tt>Transition</tt> in an atomic/transactional fashion and 
	 * automatically manages the <tt>Process</tt>'s <tt>ProcessState</tt> object.
	 * <p>
	 * Before the transition is executed, a transaction is started and the <tt>Process</tt>'s <tt>ProcessState</tt> object is loaded
	 * from the persistence store and injected into the <tt>Process</tt>. If no <tt>ProcessState</tt> exists for the <tt>Process</tt>,
	 * then a new one is instantiated and immediately saved in the persistence store. The transition's <code>doTransition()</code> method
	 * is then executed.
	 * <p>
	 * If the method completes successfully, then the <tt>Process</tt>'s <tt>ProcessState</tt> object is persisted and the transaction is committed.
	 * <p>
	 * If the method throws an exception, then the transaction is rolled back.
	 * 
	 * @param process the <tt>Process</tt> whose state is to be loaded/persisted before/after the <tt>Transition</tt> is executed
	 * @param transition the <tt>Transition</tt> to execute
	 * @throws TransitionException if the <tt>Transition</tt>'s <code>doTransition()</code> method throws a runtime exception
	 * @throws ProcessStateManagementException if an error occurs loading or persisting the </code>process</code>'s <tt>ProcessState</tt> object
	 */
	void execute(Process<? extends ProcessState> process, Transition transition)
		throws TransitionException, ProcessStateManagementException;
	
	/**
	 * Executes a <tt>Transition</tt> in an atomic/transactional fashion.
	 * <p>
	 * Before the transition is executed, a transaction is started. The transition's <code>doTransition()</code> method
	 * is then executed.
	 * <p>
	 * If the method completes successfully, then the transaction is committed.
	 * <p>
	 * If the method throws an exception, then the transaction is rolled back.
	 * 
	 * @param transition the <tt>Transition</tt> to execute
	 * @throws TransitionException  if the <tt>Transition</tt>'s <code>doTransition()</code> method throws a runtime exception
	 */
	void executeWithoutStateManagement(Transition transition) throws TransitionException;
	
	/**
	 * Executes a <tt>TransitionWithResult</tt> in an atomic/transactional fashion and 
	 * automatically manages the <tt>Process</tt>'s <tt>ProcessState</tt> object.
	 * <p>
	 * Before the transition is executed, a transaction is started and the <tt>Process</tt>'s <tt>ProcessState</tt> object is loaded
	 * from the persistence store and injected into the <tt>Process</tt>. If no <tt>ProcessState</tt> exists for the <tt>Process</tt>,
	 * then a new one is instantiated and immediately saved in the persistence store. The transition's <code>doTransition()</code> method
	 * is then executed.
	 * <p>
	 * If the method completes successfully, then the <tt>Process</tt>'s <tt>ProcessState</tt> object is persisted and the transaction is committed.
	 * <p>
	 * If the method throws an exception, then the transaction is rolled back.
	 * 
	 * @param process the <tt>Process</tt> whose state is to be loaded/persisted before/after the <tt>TransitionWithResult</tt> is executed
	 * @param transition the <tt>TransitionWithResult</tt> to execute
	 * @return the return value of the <tt>TransitionWithResult</tt>'s <code>doTransition()</code> method
	 * @throws TransitionException if the <tt>TransitionWithResult</tt>'s <code>doTransition()</code> method throws a runtime exception
	 * @throws ProcessStateManagementException if an error occurs loading or persisting the </code>process</code>'s <tt>ProcessState</tt> object
	 */
	Object execute(Process<? extends ProcessState> process, TransitionWithResult transition)
		throws TransitionException, ProcessStateManagementException;
	
	/**
	 * Executes a <tt>TransitionWithResult</tt> in an atomic/transactional fashion.
	 * <p>
	 * Before the transition is executed, a transaction is started. The transition's <code>doTransition()</code> method
	 * is then executed.
	 * <p>
	 * If the method completes successfully, then the transaction is committed.
	 * <p>
	 * If the method throws an exception, then the transaction is rolled back.
	 * 
	 * @param transition the <tt>TransitionWithResult</tt> to execute
	 * @return the return value of <tt>TransitionWithResult</tt>'s <code>doTransition()</code> method
	 * @throws TransitionException if the <tt>TransitionWithResult</tt>'s <code>doTransition()</code> method throws a runtime exception
	 */
	Object executeWithoutStateManagement(TransitionWithResult transition) throws TransitionException;
}
